package com.jse.server;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.StandardSocketOptions;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;

import com.jse.Io;
import com.jse.Js;
import com.jse.Jse;
import com.jse.server.HttpWebSocket.Listener;
import com.jse.web.Web;

/**
 * @Author 暗影之风
 * @CreateTime 2024-04-28 03:03:25
 * @Description HTTP服务器
 */
public final class JseServer
{

//	/** 读取超时时长，小于等于0表示默认 */
//	private long readTimeout;
//	/** 写出超时时长，小于等于0表示默认 */
//	private long writeTimeout;
//
//	/** 读取缓存大小 */
//	private int readBufferSize = 8192;
//	/** 写出缓存大小 */
//	private int writeBufferSize = 8192;
	
	public static void tomcat(){Js.eval(Io.readString(JseServer.class.getResourceAsStream("/META-INF/jse/tomcat.js")));};
	public static void jetty(){Js.eval(Io.readString(JseServer.class.getResourceAsStream("/META-INF/jse/jetty.js")));};
	public static void undertow(){Js.eval(Io.readString(JseServer.class.getResourceAsStream("/META-INF/jse/undertow.js")));};

	public static void await(){
		if(Jse.runing)return;
		Jse.runing=true;
		try {
			String type=Jse.conf.getString("server.type");
			if("tomcat".equals(type)){
				tomcat();
			}else if("jetty".equals(type)){
				jetty();
			}else if("undertow".equals(type)){
				undertow();
			}else new JseServer().start(Jse.conf.getInt("server.port",80));
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
	
	
    public void start(int port)
    {
    	try (ServerSocket serverSocket = new ServerSocket(port,0)) {
            serverSocket.setOption(StandardSocketOptions.SO_REUSEADDR, true);
            if(File.separatorChar=='/')serverSocket.setOption(StandardSocketOptions.SO_REUSEPORT, true);//win 无效
        	Web.init();
            while (true)
            {
                Socket socket = serverSocket.accept();
                Executors.newVirtualThreadPerTaskExecutor().submit(() -> {
                    try(socket){
                    	HttpCtx ctx=new HttpCtx();
                    	ctx.parse(socket);
                        if(ctx.getPath()==null)return;//空包不再执行
                        if(ctx.isWebsocket()) {//websocket
//                        	ctx.getRequestBody().read();
                        	Map<String, String> clientFields=new HashMap<String, String>();
                        	clientFields.putAll(ctx.headers);
                        	clientFields.put("Path",ctx.getPath());
                        	HttpWebSocket webSocket = new HttpWebSocket(ctx,clientFields,new HashMap<String, String>());
                        	webSocket.handshake();
                        	webSocket.addEventListener(new Listener() {
								
								@Override
								public void onMessage(String message, HttpWebSocket source) {
									System.out.print("收到消息"+message);
								}
								
								@Override
								public void onClose(HttpWebSocket source) {
									System.out.print("关闭");
								}
							});
//                        	boolean b=webSocket.handshake();
                        	webSocket.listen();
            				
                        }else {
                        	Web.service(ctx);
//                        	System.out.println(ctx.socket.isClosed());
                        	ByteArrayOutputStream bout=(ByteArrayOutputStream) ctx.getResponseBody();
                        	var bs=bout.toByteArray();
//                        	System.out.println(new String(bs));
                        	socket.getOutputStream().write(bs);
                        	socket.getOutputStream().flush();
                        	socket.getOutputStream().flush();
                            socket.getInputStream().close();
                        }
                    }
                    catch (Exception e)
                    {
                    	e.printStackTrace();
                    }
                });

            }
        }
        catch (Exception ignored){ignored.printStackTrace();}
    }
	
	public static String makeAcceptKey(String key) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        String text = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
        md.update(text.getBytes(), 0, text.length());
        byte[] sha1hash = md.digest();
        return Base64.getEncoder().encodeToString(sha1hash);
    }
	
	public static void main(String[] args) {
		Jse.jspath="d:/";
		Jse.webapp="d:/";
		new JseServer().start(80);
	}
	
}